package model.tokens;



import java.util.List;
import java.util.Stack;

import state.TabState;
import state.TurtleState;

import model.expression.AbstractExpression;
import model.parser.Parser;
import model.parser.ParserException;
import model.parser.ParsingData;

import expression.Expression;




/**
 * 
 * Abstract class for all types of token
 * @author KevinWang Chris James Misha Lavrov
 *
 * @param <T> any type
 */
public abstract class AbstractToken
{
    
    public AbstractToken() {}
    
    public AbstractToken(String token, ParsingData parsingData) {}
    	
    /**
     * performShuntingYard is called on all AbstractTokens because all AbstractTokens
     * knows what they are supposed to do. They will need to manipulate the opStack and the
     * outStack to pop or push tokens.
     * @param tabSt 
     * @param out 
     * 
     * @param opStack: operator stack for ShuntingYard algorithm
     * @param outStack: output stack for ShungtingYard algorithm
     */
	public abstract void convertToPostFix(Stack<AbstractToken> opStack, Stack<AbstractExpression> outStack, TabState tabSt, Stack<AbstractExpression> out) throws ParserException;
	
	public AbstractExpression getExpression()
    {
        throw ParserException.BAD_SYNTAX;
    }
	
	/**
	 * Used to convert a given token into its expression representation.
	 * @param ts
	 * @return
	 */
	public AbstractExpression getExpression(TabState ts) {
        throw ParserException.BAD_SYNTAX;
	}

	/**
	 * Every token can parse itself into an expression.
	 */
	public Stack<AbstractExpression> makeExpression(List<AbstractToken> toks,
			Stack<AbstractExpression> out, TabState tabSt, Parser parser)throws ParserException{
			
			Stack<AbstractExpression> outStack = new Stack<AbstractExpression>();
			Stack<AbstractToken> opStack = new Stack<AbstractToken>();
		     
		    for(AbstractToken t : toks)
		    {
		        t.convertToPostFix(opStack, outStack, tabSt,out); 
		    }
		     
		    while(!opStack.isEmpty())
		    {
		        /* apply top operator to output stack */
		       ((OperatorToken) opStack.pop()).makeExpression(outStack,out);
		    } 
		    return outStack;
	}

}
